import os
import sys

# 如果当前代码文件运行测试需要加入修改路径，否则后面的导包出现问题
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR))
import pymongo
import pandas as pd
import numpy as np


class updateRecall():

    def __init__(self) -> None:
        client = pymongo.MongoClient(host='127.0.0.1', port=27017)
        # 进入数据库（或者创建）
        self.DB = client['movierec']

    def update_user_history_recall(self):
        # 用户行为
        user_actionCollection = self.DB['user_action']
        user_actionDf = pd.DataFrame(list(user_actionCollection.find()))

        # 视频相似度数据
        video_simiarCollection = self.DB["video_simiar_rec"]
        video_simiarDf = pd.DataFrame(list(video_simiarCollection.find()))

        # 行为表关联视频相似度表
        action_recall_Df = pd.merge(user_actionDf, video_simiarDf, on='bv', how="left")[["uid", "rec_list"]]
        # 结果存储到用户-视频召回集
        rawdf = action_recall_Df.groupby("uid")['rec_list'].apply(lambda x: np.concatenate(list(x))).reset_index()
        user_content_recall = []
        # 过滤看过的视频
        for index, row in rawdf.iterrows():
            # 过滤掉历史观看内容和重复性推荐视频，并生成召回集
            history = []
            for index, row1 in user_actionDf.iterrows():
                history.append(row1['bv'])
            rec = list(set(row['rec_list']) - set(history))
            user_rec = {
                'uid': row['uid'],
                'recs': rec
            }
            user_content_recall.append(user_rec)
        user_recall_df = pd.DataFrame(user_content_recall)
        user_recall_df

        # 更新召回表
        user_history_recClollection = self.DB["user_history_recall"]
        user_history_recClollection.drop()
        user_history_recClollection.insert_many(user_recall_df.to_dict('records'))

        # 更新基于用户画像的召回集

    def update_profile_reacall(self):
        user_profile_Collection = self.DB['user_profile']
        user_profile_df = pd.DataFrame(list(user_profile_Collection.find()))
        u_profiles = []
        # 聚合uid操作
        g = user_profile_df.groupby("uid")
        result = {a: list(s.drop("_id", axis=1).T.to_dict().values()) for a, s in g}
        for key in result:
            # 排序拿到用户画像权重top10
            p = sorted(result[key], key=lambda items: items['weight'], reverse=True)[0:10]
            up = {
                'uid': key,
                'profile': p
            }
            u_profiles.append(up)
        # 变成 uid:[tag1,tag2,tag3...]的形式
        userProfileTags = []
        for i in u_profiles:
            tags = []
            for p in i['profile']:
                tags.append(p['profile'])
            userProfileTag = {
                'uid': i['uid'],
                'tag': tags
            }
            userProfileTags.append(userProfileTag)
        # 查询视频特征的倒排索引表，生成召回集
        user_profile_recs = []
        video_profile_inverted_table = self.DB['video_profile_inverted_table']
        # inverted_tableDf=pd.DataFrame(list(video_profile_inverted_table.find()))
        # inverted_tableDf
        for utag in userProfileTags:
            # 查出记录
            df = pd.DataFrame(list(video_profile_inverted_table.find({"tag": {"$in": utag['tag']}})))
            bvlist = []
            for index, row in df.iterrows():
                bvlist.extend(row['bvs'])
            user_profile_rec = {
                'uid': utag['uid'],
                'bvs': list(set(bvlist))
            }
            user_profile_recs.append(user_profile_rec)
        # print(user_profile_recs)
        # 存入数据库
        user_profile_recallCollection = self.DB['user_profile_recall']
        user_profile_recallCollection.drop()
        user_profile_recallCollection.insert_many(user_profile_recs)

    def update_profile_recall_byuid(self, uid):
        bvlist = []
        # 用户特征的表
        user_profile_Collection = self.DB['user_profile']
        # 视频特征的倒排索引表
        video_profile_inverted_table = self.DB['video_profile_inverted_table']
        # 对用户权重降序排序取出前10作为特征
        user_profile_df = pd.DataFrame(list(user_profile_Collection.find({"uid": uid}).sort("weight", -1).limit(10)))
        # 根据用户特征查询倒排表，生成召回集
        for user_profile_index, user_profile_row in user_profile_df.iterrows():
            df = pd.DataFrame(list(video_profile_inverted_table.find({"tag": user_profile_row['profile']})))
            for index, row in df.iterrows():
                bvlist.extend(row['bvs'])
        result = {
            "uid": uid,
            "bvs": bvlist
        }
        # 更新用户召回集
        user_profile_recallCollection = self.DB['user_profile_recall']
        user_profile_recallCollection.delete_one({"uid": uid})
        user_profile_recallCollection.insert_one(result)
